package com.hnichr.ump.build7.service.impl;

import com.alibaba.fastjson.JSON;
import com.hnichr.ump.build7.cache.PlateCache;
import com.hnichr.ump.build7.pojo.Plate;
import com.hnichr.ump.build7.service.StopService;
import com.hnichr.ump.build7.share.*;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.SimpleCriterion;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;


@Service
public class StopServiceImpl implements StopService {

    private static final Logger logger = LoggerFactory.getLogger(StopServiceImpl.class);

    @Autowired
    private MqttClient mqttClient;

    public String snapshot(){
        MqttMessage message = new MqttMessage();
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("id","NYGtiXpPy5ratyzU");
        dataMap.put("sn","b956ba98-988cd83e");
        dataMap.put("name","snapshot");
        dataMap.put("version","1.0");
        dataMap.put("timestamp",String.valueOf(new Date().getTime()));

        Map<String,Object> payloadMap = new HashMap<>();
        payloadMap.put("type","snapshot");
        payloadMap.put("body",new HashMap<>());
        dataMap.put("payload",payloadMap);
        message.setPayload(JSON.toJSONString(dataMap).getBytes());
        String imageContent=null;
        try{
            mqttClient.publish("b956ba98-988cd83e/device/message/down/snapshot", message);
            synchronized (SnapshotShare.getInstance()){
                SnapshotShare.getInstance().wait(100000L);
                imageContent = SnapshotShare.getInstance().getImageContent();
            }
        }
        catch (Exception e){
            logger.error("消息投递失败");
            return null;
        }
        return imageContent;
    }

    public boolean open(){
        MqttMessage message = new MqttMessage();
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("id","NYGtiXpPy5ratyzU");
        dataMap.put("sn","b956ba98-988cd83e");
        dataMap.put("name","gpio_out");
        dataMap.put("version","1.0");
        dataMap.put("timestamp",String.valueOf(new Date().getTime()));

        Map<String,Object> payloadMap = new HashMap<>();
        payloadMap.put("type","gpio_out");
        Map<String,Object> bodyMap = new HashMap<>();
        bodyMap.put("delay",500);
        bodyMap.put("io",0);  //[0,3]   //对应的输出 IO 编号，取值范围为[0,3]之间的整数
        bodyMap.put("value",2);  //0 断, 1 通 ,2 先通后断
        payloadMap.put("body",bodyMap);
        dataMap.put("payload",payloadMap);
        message.setPayload(JSON.toJSONString(dataMap).getBytes());
        String code = null;
        try{
            mqttClient.publish("b956ba98-988cd83e/device/message/down/gpio_out", message);
            synchronized (OpenShare.getInstance()){
                OpenShare.getInstance().wait(10000L);
                code = OpenShare.getInstance().getCode();
            }
        }
        catch (Exception e){
            logger.error("消息投递失败",e);
            return false;
        }
        return "200".equals(code);
    }

    public Page<Plate> writeListPage(Pageable page, Criteria criteria){
        List<Plate> plateList = writeListQuery(criteria);
        if(CollectionUtils.isEmpty(plateList)){
            return new PageImpl<>(new ArrayList<>(),page,0);
        }
        plateList.sort((o1, o2) -> StringUtils.compare(o1.getPlate(),o2.getPlate()));
        List<Plate> returnList = paging(plateList,page);
        return new PageImpl<>(returnList,page,plateList.size());
    }

    public List<Plate> writeListQuery(Criteria criteria){
        List<Object> criterias = criteria.getCriterions();
        if(!CollectionUtils.isNotEmpty(criterias)){
            return new ArrayList<>();
        }
        String plate = null;
        Iterator<Object> it = criterias.iterator();
        while (it.hasNext()){
            Object itObj = it.next();
            if(itObj instanceof SimpleCriterion){
                SimpleCriterion simpleCriterion = (SimpleCriterion) itObj;
                if("plate".equals(simpleCriterion.getFieldName())){
                    plate = simpleCriterion.getValue().toString();
                    break;
                }
            }
        }
        if(StringUtils.isBlank(plate)){
            return new ArrayList<>();
        }
        return writeListQuery(plate);
    }

    public List<Plate> writeListQuery(String plate){
        MqttMessage message = new MqttMessage();
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("id","Zr7O1PzBPD57Q4ku");
        dataMap.put("sn","b956ba98-988cd83e");
        dataMap.put("name","white_list_operator");
        dataMap.put("version","1.0");
        dataMap.put("timestamp",String.valueOf(new Date().getTime()));

        Map<String,Object> payloadMap = new HashMap<>();
        payloadMap.put("type","white_list_operator");
        Map<String,Object> bodyMap = new HashMap<>();
        bodyMap.put("operator_type","select");
        if(StringUtils.isBlank(plate)){
            bodyMap.put("plate","豫");
        }
        else{
            bodyMap.put("plate",plate);
        }
        bodyMap.put("sub_type","plate");
        payloadMap.put("body",bodyMap);
        dataMap.put("payload",payloadMap);
        message.setPayload(JSON.toJSONString(dataMap).getBytes());
        try{
            mqttClient.publish("b956ba98-988cd83e/device/message/down/white_list_operator", message);
            synchronized (WhitelistQueryShare.getInstance()){
                WhitelistQueryShare.getInstance().wait(10000L);
                List<Plate> plateList = WhitelistQueryShare.getInstance().getPlateList();
                if(CollectionUtils.isNotEmpty(plateList)){
                    plateList.sort((o1, o2) -> StringUtils.compare(o1.getPlate(),o2.getPlate()));
                }
                //查询结果放入缓存
                for(Plate p:plateList){
                    PlateCache.put(p.getPlate(),p.getContext());
                }
                return plateList;
            }
        }
        catch (Exception e){
            logger.error("消息投递失败");
        }
        return new ArrayList<>();
    }

    public boolean writeListAddOrUpdate(String plate,String context,String enableTime,String overdueTime,int enable){
        MqttMessage message = new MqttMessage();
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("id","Zr7O1PzBPD57Q4ku");
        dataMap.put("sn","b956ba98-988cd83e");
        dataMap.put("name","white_list_operator");
        dataMap.put("version","1.0");
        dataMap.put("timestamp",String.valueOf(new Date().getTime()));

        Map<String,Object> payloadMap = new HashMap<>();
        payloadMap.put("type","white_list_operator");
        Map<String,Object> bodyMap = new HashMap<>();
        bodyMap.put("operator_type","update_or_add");
        Map<String,Object> dldcMap = new HashMap<>();
        dldcMap.put("create_time", DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
        dldcMap.put("enable_time", enableTime);
        dldcMap.put("overdue_time", overdueTime);
        dldcMap.put("enable", enable);
        dldcMap.put("plate",plate);
        dldcMap.put("time_seg_enable",0);
        dldcMap.put("seg_time","");
        dldcMap.put("need_alarm",0);
        dldcMap.put("vehicle_code","");
        dldcMap.put("vehicle_comment",context);
        dldcMap.put("customer_id","");
        bodyMap.put("dldb_rec",dldcMap);
        payloadMap.put("body",bodyMap);
        dataMap.put("payload",payloadMap);
        message.setPayload(JSON.toJSONString(dataMap).getBytes());
        String code = null;
        try{
            mqttClient.publish("b956ba98-988cd83e/device/message/down/white_list_operator", message);
            synchronized (WhitelistAddOrDeleteShare.getInstance()){
                WhitelistAddOrDeleteShare.getInstance().wait(10000L);
                code = WhitelistAddOrDeleteShare.getInstance().getCode();
                if("200".equals(code)){
                    PlateCache.put(plate, context);
                }
            }
        }
        catch (Exception e){
            logger.error("消息投递失败");
            return false;
        }
        return "200".equals(code);
    }

    public boolean writeListDel(String[] plate){
        MqttMessage message = new MqttMessage();
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("id","Zr7O1PzBPD57Q4ku");
        dataMap.put("sn","b956ba98-988cd83e");
        dataMap.put("name","white_list_operator");
        dataMap.put("version","1.0");
        dataMap.put("timestamp",String.valueOf(new Date().getTime()));

        Map<String,Object> payloadMap = new HashMap<>();
        payloadMap.put("type","white_list_operator");
        Map<String,Object> bodyMap = new HashMap<>();
        bodyMap.put("operator_type","delete");
        bodyMap.put("plate",plate);
        payloadMap.put("body",bodyMap);
        dataMap.put("payload",payloadMap);
        message.setPayload(JSON.toJSONString(dataMap).getBytes());
        String code = null;
        try{
            mqttClient.publish("b956ba98-988cd83e/device/message/down/white_list_operator", message);
            synchronized (WhitelistAddOrDeleteShare.getInstance()){
                WhitelistAddOrDeleteShare.getInstance().wait(10000L);
                code = WhitelistAddOrDeleteShare.getInstance().getCode();
                if("200".equals(code)){
                    for(String p:plate){
                        PlateCache.remove(p);
                    }
                }
            }
        }
        catch (Exception e){
            logger.error("删除消息投递失败");
            return false;
        }
        return "200".equals(code);
    }

    public List<Plate> paging(List<Plate> ls,Pageable page) {
        List<List<Plate>> lss = ListUtils.partition(ls,page.getPageSize());
        return lss.get(page.getPageNumber());
    }

}
